// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Vector_3.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Kernel/Py_Vector_3.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

#include <CGAL/basic.h>
#include <include/Kernels.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>

const char* Vector_3_doc[] ={
"\
An object of the class Vector_3 is a vector in the three-dimensional\n\
vector space E x E x E.Geometrically spoken a vector is the difference of two points\n\
p2, p1 and denotes the direction and the distance from p1 to p2.\n\
CGAL defines a symbolic constant NULL_VECTOR. We will explicitly state where you\n\
can pass this constant as an argument instead of a vector initialized with zeros. \n\
For more details see a C++ documentation:\n\
http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Kernel_23_ref/Class_Vector_3.html",
"\
v = Vector_3( Point_3 a, Point_3 b)\n\
introduces the vector b-a.\n\n\
v = Vector_3( Segment_3 s)\n\
introduces the vector s.target()-s.source().\n\n\
v = Vector_3( Ray_3 r)\n\
introduces a vector having the same direction as r.\n\n\
v = Vector_3( Line_3 l)\n\
introduces a vector having the same direction as l.\n\n\
v = Vector_3( NULL_VECTOR);\n\
introduces a null vector v.\n\n\
v = Vector_3( hx,hy,hz,hw = 1)\n\
introduces a vector v initialized to (hx/hw, hy/hw, hz/hw).",
"v.x( self) ->  returns the x-coordinate of v, that is hx/hw.",
"v.y( self) -> returns the y-coordinate of v, that is hy/hw.",
"v.z( self) -> returns the z coordinate of v, that is hz/hw. ",
"v.hx( self) -> returns the homogeneous x coordinate.",
"v.hy( self) -> returns the homogeneous y coordinate.",
"v.hz( self) -> returns the homogeneous z coordinate.",
"v.hw( self) -> returns the homogenizing coordinate.",
"v.cartesian( self int i) -> returns the i'th Cartesian coordinate of v, starting at 0.\n\
Precondition: 0 <= i <= 2.",
"v.homogeneous( self, int i) -> returns the i'th homogeneous coordinate of v, starting with 0.\n\
Precondition: 0 <= i <= 3.",
"v.dimension( self) -> returns the dimension( selfthe constant 3).",
"v.squared_length( self) -> returns the squared_length of v.",
"v.direction( self) -> returns the direction of v.",
"v.transform( self , Aff_transformation_3 t) -> Vector_3\nreturns the vector obtained by applying t on v."
"v[i] -> returns the i'th Cartesian coordinate of v, starting at 0."
};

template<class Vector_3>
boost::python::str py_repr_Vector_3(const Vector_3& v )
{
	using namespace boost::python;
	return str("Vector_3("+ str(v.x()) +","+ str(v.y())+","+ str(v.z()) +")" );
}

template <class kernel > 
void Py_Vector_3()
{
	typedef typename kernel::Point_3 						Point_3;
	typedef typename kernel::Segment_3 						Segment_3;
 	typedef typename kernel::Vector_3 						Vector_3;
 	typedef typename kernel::Direction_3 						Direction_3;
 	typedef typename kernel::Line_3 						Line_3;
  	typedef typename kernel::Ray_3 						        Ray_3;
 	typedef typename kernel::FT 							FT;
 	typedef typename kernel::RT 							RT;

	using namespace boost::python;

        class_< Vector_3 >("Vector_3", Vector_3_doc[0],init<>())
        .def(init< const Vector_3& >(Vector_3_doc[1]))
        .def(init< const CGAL::Null_vector& >())
        .def(init< const Point_3&, const Point_3& >())
        .def(init< const Segment_3& >())
        .def(init< const Ray_3& >())
        .def(init< const Line_3& >())
        .def(init< const FT&, const FT&, const FT& >())
        .def(init< const FT&, const FT&, const FT&, const FT& >())

        .def(init< const double&, const double&, const double& >())
        .def(init< const double&, const double&, const double&, const double& >())

#if CGAL_VERSION_NR < 1030301000
        .def("x", &Vector_3::x, by_cref(), Vector_3_doc[2])
        .def("y", &Vector_3::y, by_cref(), Vector_3_doc[3])
        .def("z", &Vector_3::z, by_cref(), Vector_3_doc[4])
        .def("hx", &Vector_3::hx, by_cref(), Vector_3_doc[5])
        .def("hy", &Vector_3::hy, by_cref(), Vector_3_doc[6])
        .def("hz", &Vector_3::hz, by_cref(), Vector_3_doc[7])
        .def("hw", &Vector_3::hw, Vector_3_doc[8])
        .def("cartesian", &Vector_3::cartesian, by_cref(), Vector_3_doc[9])
        .def("homogeneous", &Vector_3::homogeneous, Vector_3_doc[10])
#else
        .def("x", &Vector_3::x, typename Value_or_cref<typename kernel::Compute_x_3, Vector_3 > ::type (), Vector_3_doc[2])
        .def("y", &Vector_3::y, typename Value_or_cref<typename kernel::Compute_y_3, Vector_3 > ::type(), Vector_3_doc[3])
        .def("z", &Vector_3::z, typename Value_or_cref<typename kernel::Compute_z_3, Vector_3 > ::type(), Vector_3_doc[4])
        .def("hx", &Vector_3::hx, typename Value_or_cref<typename kernel::Compute_hx_3, Vector_3 > ::type(), Vector_3_doc[5])
        .def("hy", &Vector_3::hy, typename Value_or_cref<typename kernel::Compute_hy_3, Vector_3 > ::type(), Vector_3_doc[6])
        .def("hz", &Vector_3::hz, typename Value_or_cref<typename kernel::Compute_hz_3, Vector_3 > ::type(), Vector_3_doc[7])
        .def("hw", &Vector_3::hw, typename Value_or_cref<typename kernel::Compute_hw_3, Vector_3 > ::type(), Vector_3_doc[8])
        .def("cartesian", &Vector_3::cartesian, typename Value_or_cref<typename kernel::Compute_x_3, Vector_3 > ::type(), Vector_3_doc[9])
        .def("homogeneous", &Vector_3::homogeneous, typename Value_or_cref<typename kernel::Compute_hw_3, Vector_3 > ::type(), Vector_3_doc[10])
#endif
        .def("dimension", &Vector_3::dimension, Vector_3_doc[11])
        .def("squared_length", &Vector_3::squared_length, Vector_3_doc[12])
        .def("direction", &Vector_3::direction, Vector_3_doc[13])
        .def("transform", &Vector_3::transform, Vector_3_doc[14])
#if CGAL_VERSION_NR < 1030301000
	.def("__getitem__", &Vector_3::operator[], by_cref(), Vector_3_doc[15])
#else
	.def("__getitem__", &Vector_3::operator[], typename Value_or_cref<typename kernel::Compute_x_3, Vector_3 > ::type(), Vector_3_doc[15])
#endif
	.def("__repr__", &py_repr_Vector_3<Vector_3>)
	.def(self == self)
	.def(self != self)
        .def( -self )
        .def( self - self )
        .def( self + self )
	.def( self * self )
	.def( self * double() )
	.def( double() * self)
        .def( self / double() )
/*        .def( self + CGAL::Origin() )*/
        .def( CGAL::Origin() + self )
	;
}

void export_Vector_3()
{
	Py_Vector_3<K>();
}
